
package com.beiding.config;

import io.undertow.Undertow;
import io.undertow.servlet.api.SecurityConstraint;
import io.undertow.servlet.api.SecurityInfo;
import io.undertow.servlet.api.TransportGuaranteeType;
import io.undertow.servlet.api.WebResourceCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
import org.xnio.SslClientAuthMode;

import javax.servlet.Servlet;

@Configuration
public class RedirectConfig extends WebSecurityConfigurerAdapter {



    //基于Redis的Session注册表
    private SpringSessionBackedSessionRegistry sessionRegistry;

    //基于Redis的Session仓库
    private RedisOperationsSessionRepository repository;

    @Autowired
    public void setRepository(RedisOperationsSessionRepository repository) {
        this.repository = repository;
        sessionRegistry = new SpringSessionBackedSessionRegistry<>(repository);

    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/message").authenticated()
                .anyRequest().permitAll()
                .and().csrf().disable().headers().frameOptions().sameOrigin();


        http.sessionManagement()
                .sessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy(
                        sessionRegistry
                ))
                .invalidSessionUrl("/user/login")
                .maximumSessions(1)
                .sessionRegistry(sessionRegistry)
                .expiredUrl("/user/login");


    }


    @Configuration
    @ConditionalOnClass({Servlet.class, Undertow.class, SslClientAuthMode.class})
    @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
    public static class EmbeddedUndertow {

        @Bean
        public UndertowServletWebServerFactory undertowServletWebServerFactory() {

            UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
            factory.addBuilderCustomizers((UndertowBuilderCustomizer) builder -> builder.addHttpListener(80, "0.0.0.0"));

            //将80端口重定向到443端口
             factory.addDeploymentInfoCustomizers(deploymentInfo -> {
                deploymentInfo.addSecurityConstraint(new SecurityConstraint()
                        .addWebResourceCollection(new WebResourceCollection()
                                .addUrlPattern("/*")).setTransportGuaranteeType(TransportGuaranteeType.CONFIDENTIAL)
                        .setEmptyRoleSemantic(SecurityInfo.EmptyRoleSemantic.PERMIT))
                        .setConfidentialPortManager(exchange -> 443);
            });


            return factory;
        }

    }

}
